######################################################################
# Time-stamp: <05/08/09 16:59:36 ostolop>
#
# Package: EP::Core::Data::Parser::seq::xml_table
#
# Expression Data Parser Classes
######################################################################
package EP::Core::Data::Parser::seq::xml_table;

use strict;
use base qw ( EP::Core::Data::Parser );

use EP::Config;
use EP::Common;
use EP::Common::General;
use EP::Common::Error qw ( :try );
use EP::EPC::Core;
use EP::EPC::Core::Component;

use Bio::DB::GFF;

use File::Temp;
use File::Spec;

use XML::LibXSLT;

# sub: parse_data
#   processes the uploaded data and creates a corresponding entry in the database
sub parse_data {
  my $self = shift;

  my $data = $self->upload_data ();

  my $cur_folder = $self->{epc}->{session}->current_folder;
  if ( $self->_process_uploaded_data ( $data ) ) {
    my ($dataset) = EP::Common::DBI->do_transaction (
     sub {
       my ($self) = @_;
       my $dataset = EP::Common::DBI::Dataset->create ({ name         => $data->{dataset_name} . " : ". localtime,
							 description  => $self->{query}->param ( "dataset_description" ) . "",
							 type         => "seq",
							 species      => $self->{query}->param ( "dataset_species" ) . "" || "unknown",
							 folder       => $cur_folder->id,
							 ep_session   => $self->{epc}->{current_user}->session_only ? $self->{epc}->{session}->id : undef,
							 owner        => $self->{epc}->{current_user},
							 group_write  => 0,
							 group_read   => 1,
							 other_read   => 0
						       });

       $self->_write_dataset_data ( $dataset, $data ); # or die "Failed to write the dataset data!";
       return $dataset;
     }, $self );

    return $dataset;
  }

  die "Failed to process uploaded data.";
}
# sub: _write_dataset_data
#   Writes the sequence data from the dataset to a file on disk in fasta format
#   Expects the sequence data to be an instance of a <Bio::SeqIO> object
#   If the start and end basepair position are set for the dataset object, 
#   the corresponding subpart of the sequences is written to file
# parameters:
#   dataset - Which dataset to write to disk
# returns:
#   1 upon successfull writing of the sequences to the file
# see also:
#   <EP::Core::Dataset::Data::seq::start_bp> <EP::Core::Dataset::Data::seq::end_bp>
sub _write_dataset_data {
  my $self = shift;
  my ($dataset, $data) = @_;
  my (@seq_notfound);

  my $stream = $data->{sequences};
  my $folder   = $EP::Config::h->{EPNG_USRDATA_PATH} . "/" . $dataset->folder->location;
  my $filename = $dataset->filename;

  # always write fasta format
  my $out = Bio::SeqIO->new ( -file => ">$folder/$filename.fasta",
			      -format => "fasta" );

  my $start_bp = $dataset->data->start_bp();
  my $end_bp = $dataset->data->end_bp();

  my $i = 1;
  while ( my $seq = $stream->next_seq() ) {
    ### UGlY HACK ###
    # the get_seq_stream and get_Stream_by_name do no actually return the same objects
    # so we can only get the id if it is coming from get_Stream_by_name
    my $try_id = $stream->{ids}->[0] if ref( $stream ) eq 'Bio::DB::GFF::ID_Iterator';

    try {
      if ( $start_bp && $end_bp ) {
	# Do we only want part of the sequence ?
	my $subseq = $seq->subseq ( $start_bp, $end_bp );
	$out->write_seq($subseq);
      } else {
	$out->write_seq($seq);
      }
    } otherwise {
      push @seq_notfound, $try_id if $try_id;
    };
  }

  # print warning if some id's where not found
  warn "The sequences for the following IDs were not obtained: " . join( " ", @seq_notfound) 
      if scalar(@seq_notfound) > 0;


  `perl -i -ne 'chomp if not /^>/; print "\n" if /^>/ and \$. > 1; print;' $folder/$filename.fasta`;
  warn "Successfully wrote sequence dataset $filename.fasta to folder $folder" if DEBUG;

  return 1;
}

# sub: _process_uploaded_data
# Processes uploaded data (identifies file, reads in the related data, sets it up for further use)
# WRITE MORE HERE.
sub _process_uploaded_data {
  my $self = shift;
  my ( $data ) = @_;

  my $XSLT = new XML::LibXSLT;
  my $import_xml_table_xslt = $XSLT->parse_stylesheet_file( "$EP::Config::h->{HTML_ROOT}/static/xsl/import_xml_table.xsl" );
  my $results = $import_xml_table_xslt->transform_file ( $data->{data},
							 XML::LibXSLT::xpath_to_string ( format => "fasta" ) );

  my $t = new File::Temp;
  $import_xml_table_xslt->output_fh ( $results, $t );

  $import_xml_table_xslt->output_fh ( $results, STDERR );

  $data->{sequences} = Bio::SeqIO->new ( -file  => "$t",
					 -format => 'fasta' );

  unlink $data->{data};
  return OK;
}

1;
